package github.sf.fw.tools.tree.impl;


import github.sf.fw.tools.spi.SpiFactory;
import github.sf.fw.tools.tree.BaseNode;
import github.sf.fw.tools.tree.BaseTreeNode;
import github.sf.fw.tools.tree.Node;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 子节点排序工具，递归构建法未对功能进行测试
 */
public class RecursionTreeBuilder extends BaseTreeBuilder {
    private final AtomicInteger counter = new AtomicInteger(0);
    private final static int MAX = 10000;

    @Override
    public Node buildTree(List<Node> rootNodes) {
        clearTreeNodeList();
        initialize(rootNodes);
        BaseTreeNode rootTreeNode = (BaseTreeNode) createTreeNode();
        for (Node node : getRoots()) {
            if (BaseNode.class.isAssignableFrom(node.getClass())) {
                BaseTreeNode treeNode = (BaseTreeNode) createTreeNode();
                treeNode.copyFrom(node);
                rootTreeNode.addChildren(treeNode);
                recursionAdd(treeNode);
            }
        }
        rootTreeNode.sortChildren();
        return rootTreeNode.obtainChildren().size() == 1 ? rootTreeNode.obtainChildren().get(0) : rootTreeNode;
    }

    private void recursionAdd(BaseTreeNode node) {
        if (counter.incrementAndGet() > MAX) {
            return;
        }
        node.addPath(node.obtainNodeId().toString());
        List<Node> childNodes = getIdAndChildNode().get(node.obtainNodeId());
        if (childNodes != null) {
            for (Node childNode : childNodes) {
                BaseTreeNode treeNode = (BaseTreeNode) createTreeNode();
                treeNode.copyFrom(childNode);
                treeNode.addPathList(node.obtainPath());
                node.addChildren(treeNode);
                recursionAdd(treeNode);
            }
        }
        //子节点排序
        node.sortChildren();
        addNodeToTreeNodeList(node);
    }

    @Override
    public List<Node> getChildren(Node node) {
        return null;
    }

    @Override
    public Node createTreeNode() {
        return SpiFactory.getObject(BaseTreeNode.class, treeNodeImpl);
    }
}
